package lyc.springcloud.admin.service.impl.systemManagerServiceImpl;

import lombok.extern.slf4j.Slf4j;
import lyc.springcloud.admin.dao.systemManagerDao.RoleManagerDao;
import lyc.springcloud.admin.dto.systemManagerDto.RoleManagerDto;
import lyc.springcloud.admin.service.def.systemManagerService.RoleManagerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
@Slf4j
public class RoleManagerServiceImpl implements RoleManagerService {
    @Autowired
    private RoleManagerDao roleManagerDao;


    /**
     * 角色管理---查询所有启用资源tree（包括菜单和功能）
     * */
    @Override
    public Map<String, Object> selectEnableResourceTree() {
        String root_id = "root_node";
        // 所有资源tree
        Map<String, Object> rootTree = new HashMap<>();
        // root下所有资源tree
        List<Map> resourceTreeList = new ArrayList<Map>();
        // 查询所有资源---平铺数据
        List<Map> allResourceList = roleManagerDao.selectEnableResourceTree();
        // 一级资源---平铺数据
        List<Map> all_level1_resourceList = new ArrayList<Map>();

        // 搞定一级菜单(menu不需要展示root级的菜单，进来只看到收起的所有一级菜单)
        for (Map item : allResourceList) {
            String parentId = (String) item.get("parentId");
            if (parentId.equals(root_id)) {
                all_level1_resourceList.add(item);
            }
        }
        // 一级菜单---加children属性
        for (Map item : all_level1_resourceList) {
            item.put("children", getRestNode((String) item.get("resourceId"), allResourceList));
        }

        // 生成menuTree菜单
        resourceTreeList.addAll(all_level1_resourceList);

        // 最终生成roottree
        rootTree.put("resourceId", "root_node");
        rootTree.put("title", "全部资源");
        rootTree.put("isLeaf", 0);
        rootTree.put("children", resourceTreeList);
        return rootTree;
    }

    private List<Map> getRestNode(String parentId, List<Map> allMenuList) {
        // 也许这种递归写法可以支持n级的tree分支，但前端的iview组件menu多一级就要多写一层dom，目前3级
        List<Map> restNodeList = new ArrayList<Map>();
        for (Map item : allMenuList) {
            String pId = (String) item.get("parentId");
            if(pId.equals(parentId)) {
                restNodeList.add(item);
            }
        }
        for(Map item : restNodeList) {
            String pId = (String) item.get("parentId");
            item.put("children", getRestNode((String) item.get("resourceId"), allMenuList));
        }
        // 递归退出条件
        if (restNodeList.size() == 0) {
            return null;
        }
        return restNodeList;
    }

    /**
     * 角色管理---根据角色ID查询所有角色下启用的资源tree（包括菜单和功能）
     * */
    @Override
    public Map<String, Object> selectEnableResourceTreeByRoleId(String roleId) {
        String root_id = "root_node";
        // 当前角色拥有的资源id列表
        List<String> roleResourceIdList = roleManagerDao.selectEnableResourceTreeByRoleId(roleId);
        // 所有资源tree
        Map<String, Object> rootTree = new HashMap<>();
        // root下所有资源tree
        List<Map> resourceTreeList = new ArrayList<Map>();
        // 查询所有资源---平铺数据
        List<Map> allResourceList = roleManagerDao.selectEnableResourceTree();
        // 一级资源---平铺数据
        List<Map> all_level1_resourceList = new ArrayList<Map>();

        // 搞定一级菜单(menu不需要展示root级的菜单，进来只看到收起的所有一级菜单)
        for (Map item : allResourceList) {
            String resourceId = (String) item.get("resourceId"); // 当前资源ID
            String parentId = (String) item.get("parentId"); // 父级资源ID
            Integer isLeaf = (Integer) item.get("isLeaf"); // 是否为叶子节点（用作判断是否为叶子节点）
            String icon = (String) item.get("icon"); // 是否有icon（用作判断是否为叶子节点）
            if (parentId.equals(root_id)) {
                if(roleResourceIdList.contains(resourceId) && isLeaf == 1 && icon == null) {
                    item.put("checked", true);
                }
                all_level1_resourceList.add(item);
            }
        }
        // 一级菜单---加children属性
        for (Map item : all_level1_resourceList) {
            item.put("children", getRestNodeWithChecked((String) item.get("resourceId"), allResourceList, roleResourceIdList));
        }

        // 生成menuTree菜单
        resourceTreeList.addAll(all_level1_resourceList);

        // 最终生成roottree
        rootTree.put("resourceId", "root_node");
        rootTree.put("title", "全部资源");
        rootTree.put("isLeaf", 0);
        rootTree.put("children", resourceTreeList);
        return rootTree;
    }

    private List<Map> getRestNodeWithChecked(String parentId, List<Map> allMenuList, List<String> roleResourceIdList) {
        // 也许这种递归写法可以支持n级的tree分支，但前端的iview组件menu多一级就要多写一层dom，目前3级
        List<Map> restNodeList = new ArrayList<Map>();
        for (Map item : allMenuList) {
            String resourceId = (String) item.get("resourceId"); // 当前资源ID
            String pId = (String) item.get("parentId"); // 父级资源ID
            Integer isLeaf = (Integer) item.get("isLeaf"); // 是否为叶子节点（用作判断是否为叶子节点）
            String icon = (String) item.get("icon"); // 是否有icon（用作判断是否为叶子节点）
            if(pId.equals(parentId)) {
                if(roleResourceIdList.contains(resourceId) && isLeaf == 1 && icon == null) {
                    item.put("checked", true);
                }
                restNodeList.add(item);
            }
        }
        for(Map item : restNodeList) {
            String pId = (String) item.get("parentId");
            item.put("children", getRestNodeWithChecked((String) item.get("resourceId"), allMenuList, roleResourceIdList));
        }
        // 递归退出条件
        if (restNodeList.size() == 0) {
            return null;
        }
        return restNodeList;
    }


    /**
     * 角色管理---新增
     * */
    @Override
    public void roleMng_insert(RoleManagerDto params) {
        // 生成uuid，把新增数据插入role表
        String roleId = UUID.randomUUID().toString().replaceAll("-", "");
        params.setRoleId(roleId);
        roleManagerDao.roleMng_insert(params);

        // 生成role表 和role_resource表关联关系
        String[] resourceIds = params.getResourceIds().split(",");
        List<Map> list = new ArrayList<>();
        for (String id : resourceIds) {
            Map map = new HashMap();
            map.put("roleId", roleId);
            map.put("resourceId", id);
            list.add(map);
        }
        roleManagerDao.role_resource_insert(list);
    }

    /**
     * 角色管理---编辑
     * */
    @Override
    public void roleMng_update(RoleManagerDto params) {
        roleManagerDao.roleMng_update(params);

        // 资源编辑可增可减，必须先全物理删，再全加
        String roleId = params.getRoleId();
        // 先全删---根据roleId删除关联资源
        roleManagerDao.role_resource_delete(roleId);
        // 再全加---生成role表 和role_resource表关联关系
        String[] resourceIds = params.getResourceIds().split(",");
        List<Map> list = new ArrayList<>();
        for (String id : resourceIds) {
            Map map = new HashMap();
            map.put("roleId", roleId);
            map.put("resourceId", id);
            list.add(map);
        }
        roleManagerDao.role_resource_insert(list);
    }

    /**
     * 角色管理---查询
     * */
    @Override
    public Map<String, Object> roleMng_select(RoleManagerDto params) {
        params.setPageNum((params.getPageNum()-1) * params.getPageSize());
        Map<String, Object> map = new HashMap<>();
        map.put("list", roleManagerDao.roleMng_select(params));
        map.put("total", roleManagerDao.roleMng_select_count());
        return map;
    }

    /**
     * 角色管理---删除
     * */
    @Override
    public void roleMng_delete(String params) {
        List list = Arrays.asList(params.split(","));
        roleManagerDao.roleMng_delete(list);
        // mapper里有根据roleId删除role_resource关联的sql，但只是单条删除，在这循环删除，不另外写循环sql
        for(Object roleId : list) {
            roleManagerDao.role_resource_delete(roleId);
        }
    }
}
